﻿using System.IO;
using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;

namespace Marbles.CMS.Controls
{
    public partial class FileExplorer : System.Web.UI.UserControl
    {

        [Category("Appearance")]
        public Color HighlightBackColor
        {
            get
            {
                object obj = ViewState["HighlightBackColor"];
                if (obj == null) { return System.Drawing.SystemColors.Highlight; }
                return (Color)obj;
            }
            set { ViewState["HighlightBackColor"] = value; }
        }

        [Category("Appearance")]
        public Color HighlightForeColor
        {
            get
            {
                object obj = ViewState["HighlightForeColor"];
                if (obj == null) { return System.Drawing.SystemColors.MenuHighlight; }
                return (Color)obj;
            }
            set { ViewState["HighlightForeColor"] = value; }
        }

        [Category("Behaviour")]
        public string RootFolder
        {
            get
            {
                object obj = ViewState["RootFolder"];
                if (obj == null) { return string.Empty; }
                return obj.ToString();
            }
            set { ViewState["RootFolder"] = value; }
        }

        [Category("Behaviour")]
        public int Columns
        {
            get
            {
                object obj = ViewState["Columns"];
                if (obj == null) { return 5; }
                return Convert.ToInt32(obj);
            }
            set { ViewState["Columns"] = value; }
        }

        [Category("Behaviour")]
        public bool PopulateOnDemand
        {
            get
            {
                object obj = ViewState["PopulateOnDemand"];
                if (obj == null) { return true; }
                return Convert.ToBoolean(obj);
            }
            set { ViewState["PopulateOnDemand"] = value; }
        }

        [Category("Behaviour")]
        public string SelectedFolder
        {
            get
            {
                if (this.treeDir.SelectedNode == null)
                {
                    return this.RootFolder;
                }

                return this.treeDir.SelectedNode.Value;
            }
        }

        [Category("Behaviour")]
        public string SelectedMappedFolder
        {
            get
            {
                if (string.IsNullOrEmpty(this.SelectedFolder)) { return string.Empty; }
                try
                {
                    return Server.MapPath(this.SelectedFolder);
                }
                catch { return this.SelectedFolder; }
            }
        }

        [Category("Behaviour")]
        public string SelectedFilename
        {
            get
            {
                object obj = ViewState["SelectedFilename"];
                if (obj == null) { return string.Empty; }
                return obj.ToString();
            }
        }

        internal string SelectedFilenameSet
        {
            set
            {
                ViewState["SelectedFilename"] = value;
            }
        }

        [Category("Behaviour")]
        public string SelectedMappedFilename
        {
            get
            {
                if (this.SelectedFilename == string.Empty) { return string.Empty; }
                return Path.Combine(this.SelectedMappedFolder, this.SelectedFilename);
            }
        }

        public event EventHandler FolderSelectionChanged;
        public event EventHandler FileSelectionChanged;


        internal string MappedRootFolder
        {
            get
            {
                try
                {
                    return Server.MapPath(RootFolder);
                }
                catch { return RootFolder; }
            }
        }

        [Category("Appearance")]
        public Unit Width
        {
            get { return pnlMain.Width; }
            set { pnlMain.Width = value; }
        }

        [Category("Appearance")]
        public Unit Height
        {
            get { return pnlMain.Height; }
            set { pnlMain.Height = value; }
        }

        [Category("Appearance")]
        public Unit FolderSplitPosition
        {
            get
            {
                if (cellSplit1.Width.IsEmpty)
                {
                    cellSplit1.Width = new Unit(150, UnitType.Pixel);
                }

                return cellSplit1.Width;
            }
            set
            {
                cellSplit1.Width = value;
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (!Page.IsPostBack) { InitialiseForm(); }
            LoadFiles();
            this.tblMain.Height = this.Height;
            cellSplit2.Width = new Unit(this.Width.Value - cellSplit1.Width.Value, UnitType.Pixel);
            this.cellSplit1.Height = this.Height;
            this.cellSplit2.Height = this.Height;
            pnlSplit1.Width = this.cellSplit1.Width;
            pnlSplit2.Width = this.cellSplit2.Width;
        }

        private void InitialiseForm()
        {
            Resources.CMSResources res = new CMS.Resources.CMSResources();
            TreeNode node = new TreeNode();
            node.PopulateOnDemand = false;
            node.Text = this.RootFolder;
            node.Value = this.RootFolder;
            node.ToolTip = node.Value;
            node.ImageUrl = res.FolderUrl;
            LoadFolders(node, this.MappedRootFolder);
            treeDir.Nodes.Clear();
            treeDir.Nodes.Add(node);
            LoadFiles();
        }

        private int LoadFolders(TreeNode parent, string mappedpath)
        {
            try
            {
                string[] dirs = Directory.GetDirectories(mappedpath, "*.*", SearchOption.TopDirectoryOnly);
                Resources.CMSResources res = new CMS.Resources.CMSResources();

                foreach (string s in dirs)
                {
                    DirectoryInfo info = new DirectoryInfo(s);
                    TreeNode node = new TreeNode();
                    node.Expanded = false;
                    node.Text = info.Name;
                    node.PopulateOnDemand = this.PopulateOnDemand;
                    if (parent.Value != "/") { node.Value = parent.Value + "/" + info.Name; } else { node.Value = parent.Value + info.Name; }
                    node.ToolTip = node.Value;
                    node.ImageUrl = res.FolderUrl;
                    if (!this.PopulateOnDemand) { LoadFolders(node, s); }

                    parent.ChildNodes.Add(node);
                }

                return dirs.Length;
            }
            catch
            {                
            }
            return 0;
        }

        private void LoadFiles()
        {
            string[] files = Directory.GetFiles(this.SelectedMappedFolder);
            int i = 0;
            TableRow row = null;
            tblFiles.Rows.Clear();

            foreach (string filename in files)
            {
                FileInfo info = new FileInfo(filename);
                if (row == null) { row = new TableRow(); i = 0; }

                row.Cells.Add(CreateCell(info));

                if (i >= this.Columns - 1)
                {
                    tblFiles.Rows.Add(row);
                    i = 0;
                    row = null;
                }
                i++;
            }

            if (row != null)
            {
                tblFiles.Rows.Add(row);
            }

        }


        private TableCell CreateCell(FileInfo file)
        {
            TableCell cell = new TableCell();
            LinkButton btn = new LinkButton();
            btn.ID = file.Name;
            btn.CommandArgument = file.Name;
            btn.Text = file.Name;
            cell.Style.Add("cursor", "hand");
            btn.ForeColor = Color.Black;
            btn.Attributes.Add("onmouseover", string.Format("this.style.color='{1}';", ColorTranslator.ToHtml(this.HighlightBackColor), ColorTranslator.ToHtml(this.HighlightForeColor)));
            btn.Attributes.Add("onmouseout", string.Format("this.style.color='{1}';", ColorTranslator.ToHtml(cell.BackColor), ColorTranslator.ToHtml(btn.ForeColor)));
            cell.Controls.Add(btn);
            cell.ToolTip = string.Format("Date Modified: {0} {1}\nSize: {2}", file.LastWriteTime.ToShortDateString(), file.LastWriteTime.ToShortTimeString(), GetFileLength(file.Length));
            cell.Attributes.Add("onmouseover", string.Format("this.style.background='{0}';this.style.color='{1}';", ColorTranslator.ToHtml(this.HighlightBackColor), ColorTranslator.ToHtml(this.HighlightForeColor)));
            cell.Attributes.Add("onmouseout", string.Format("this.style.background='{0}';this.style.color='{1}';", ColorTranslator.ToHtml(cell.BackColor), ColorTranslator.ToHtml(cell.ForeColor)));
            cell.Wrap = false;
            btn.Click += new EventHandler(fileButton_Click);
            return cell;
        }

        protected void fileButton_Click(object sender, EventArgs e)
        {
            LinkButton btn = sender as LinkButton;
            SelectedFilenameSet = btn.CommandArgument;
            if (FileSelectionChanged != null) { FileSelectionChanged(this, EventArgs.Empty); }
        }

        protected void TreeDir_SelectedNodeChanged(object sender, EventArgs e)
        {
            LoadFiles();
            if (FolderSelectionChanged != null) { FolderSelectionChanged(this, EventArgs.Empty); }
        }

        protected void TreeDir_TreeNodePopulate(object sender, TreeNodeEventArgs e)
        {
            if (!PopulateOnDemand) { return; }

            string mappedpath = e.Node.Value;

            try { mappedpath = Server.MapPath(mappedpath); }
            catch { mappedpath = e.Node.Value; }
            int count = LoadFolders(e.Node, mappedpath);
            if (count <= 0) { LoadFiles(); }
        }

        private string GetFileLength(long bytes)
        {
            long value = bytes;

            if (bytes <= 1024)
            {
                return string.Format("{0} bytes", bytes);
            }

            value = value / 1024;

            if (value <= 1024)
            {
                return string.Format("{0} KB", value);
            }

            value = value / 1024;

            return string.Format("{0} MB", value);
        }
    }
}